package com.ruoyi.web.controller.exam;

import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.MimeTypeUtils;
import com.ruoyi.exam.domain.CompetitionExam;
import com.ruoyi.exam.domain.CompetitionExamImport;
import com.ruoyi.exam.service.ICompetitionExamService;
import com.ruoyi.file_info.service.ICompetitionFileInfoService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;



/**
 * 成绩管理Controller
 * 
 * @author WXY
 * @date 2023-11-21
 */
@RestController
@RequestMapping("/system/exam")
public class CompetitionExamController extends BaseController
{
    @Autowired
    private ICompetitionExamService competitionExamService;

    @Autowired
    private ICompetitionFileInfoService competitionFileInfoService;



    /**
     * 查询成绩管理列表
     */
    @GetMapping("/list")
    public TableDataInfo list(CompetitionExam competitionExam)
    {
        startPage();
        List<CompetitionExam> list = competitionExamService.selectCompetitionExamList(competitionExam);
        return getDataTable(list);
    }

    /**
     * 导出考场安排列表
     */
    @Log(title = "成绩管理", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, CompetitionExam competitionExam)
    {
        List<CompetitionExam> list = competitionExamService.selectCompetitionExamList(competitionExam);
        ExcelUtil<CompetitionExam> util = new ExcelUtil<CompetitionExam>(CompetitionExam.class);
        util.exportExcel(response, list, "成绩管理数据");
    }

    /**
     * 成绩管理导出
     * 暂定为模板
     */
    @Log(title = "成绩管理", businessType = BusinessType.EXPORT)
    @PostMapping("/exportExam")
    public void exportExam(HttpServletResponse response, CompetitionExamImport competitionExamImport)
    {
        List<CompetitionExamImport> list = competitionExamService.selectCompetitionExamListImport(competitionExamImport);
        ExcelUtil<CompetitionExamImport> util = new ExcelUtil<CompetitionExamImport>(CompetitionExamImport.class);
        util.exportExcel(response, list, "成绩管理数据");
    }


    /**
     * 获取成绩管理详细信息
     */
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        return success(competitionExamService.selectCompetitionExamById(id));
    }

    /**
     * 新增成绩管理
     */
    @Log(title = "成绩管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody CompetitionExam competitionExam){
        //执行自动分配考场
        int i = competitionExamService.updateCompetitionExamByMap(competitionExam);
        if(i == 1){
            return AjaxResult.success();
        }else if (i == 99){
            return AjaxResult.error("该赛事参赛人数为0,不可分配考场!");
        }
        return AjaxResult.error("考试场地不满足要求!座位安排应不少于"+ i +"个!!");

    }
//    {
//        return toAjax(competitionExamService.insertCompetitionExam(competitionExam));
//    }

    /**
     * 修改成绩管理
     */
    @Log(title = "成绩管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody CompetitionExam competitionExam)
    {
        if(competitionExamService.updateCompetitionExam(competitionExam) == 0){
            return AjaxResult.error("您输入的考场号和座位号已经被占用!");
        }

        return AjaxResult.success();
    }

    /**
     * 删除成绩管理
     */
    @Log(title = "成绩管理", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        return toAjax(competitionExamService.deleteCompetitionExamByIds(ids));
    }


    @Log(title = "成绩导入", businessType = BusinessType.IMPORT)
    @PostMapping("/importData")
//    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
//    {
//
//        // 上传文件初始自定义
//        String filePath = RuoYiConfig.getUploadPath();
//        String Path = "/exam";
//        String fileName = "成绩上传源文件";
//        String[] myArray = MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION;
//        String operName = SecurityUtils.getUsername();
//
//        // 上传并返回新文件名称
//        String fileNewName = FileUploadUtils.upload(filePath,Path,fileName,operName,file,myArray);
//        System.out.println(fileNewName);
//
//        //调用方法开始解析excel
//        ExcelUtil<CompetitionExamImport> util = new ExcelUtil<CompetitionExamImport>(CompetitionExamImport.class);
//        List<CompetitionExamImport> CompetitionExamImportList = util.importExcel(file.getInputStream());
//        String message = competitionExamService.importExam(CompetitionExamImportList, updateSupport, operName);
//        return success(message);
//    }

    public CompletableFuture<AjaxResult> importData(MultipartFile file, boolean updateSupport) throws Exception {
        /**
         * 思考!!!!!!!!!!
         * 2023-12-15
         * 这个接口主要负责三个功能
         * 1.保存用户上传的文件
         * 2.将文件信息插入文件管理数据库
         * 3.解析上传的excel,获取考生的成绩
         *
         * 保存文件的命名规则:自定义名字 + 上传人的用户名 + 上传时间
         * 自定义名称:快速对不同的文件进行分类
         * 上传人的用户名:"冤有头,债有主"
         * 上传时间:快速查看文件的上传时间
         * 其中,上传人的用户名,在文件管理表中也需要插入对应的数据
         *
         * 其中: 1,3,是最耗时间的操作,多个耗时间的操作放在同一个接口中,会导致这个接口的响应速度变慢
         * 为了解决响应速度的问题,需要重写接口,并解决一系列相应的问题
         *
         * 思考点1:提高接口的响应速度,怎么做? 新建一个线程,新线程执行1和2操作,当前线程执行3操作
         * 思考点2:经过对源码的分析,已知想要获取当前操作人的用户名,可用SecurityUtils.getUsername()这个方法
         * 但是,这个方法是依赖当前线程的,即:从当前线程中去判断由谁发起的请求,以获取操作人的用户名
         * 一但让新线程去执行1和2的操作,则无法满足文件命名规则和文件管理中,上传人这一字段的写入,怎么解决?
         */
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        String clientIP = request.getRemoteAddr();
        System.out.println(clientIP);
        String protocol = request.getScheme();
        int port = request.getServerPort();

        String filePath = RuoYiConfig.getUploadPath(); //获取默认路径
        String Path = "/exam"; //路径补充
        String fileName = "成绩上传源文件"; //自定义名字
        String[] myArray = MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION; //允许的文件类型,xls,xlsx
        String operName = SecurityUtils.getUsername(); //获取当前操作人的用户名
        final String[] message = new String[1]; //返回的信息
        AtomicBoolean isExceptionOccurred = new AtomicBoolean(false);

        /**
         * 解决说明:
         *
         * 创建一个 CompletableFuture 对象来表示上传操作的结果
         * 选择 CompletableFuture 的原因:
         * CompletableFuture 的链式调用会自动处理线程之间的同步和结果传递。
         *
         * 利用多线程,同时进行文件上传和文件解析,以提高接口的响应速度
         * 上传文件FileUploadUtils.upload方法中,我将文件的名称规则定为: 自定义名字 + 上传人的用户名 + 上传时间
         * 获取上传人的用户名,这个方法依赖的是当前线程,为了提高速度,新建了一个线程,但是,一但新建一个线程,则无法获取上传人的用户名
         * 在不改变文件命名规则的前提下,可以在当前线程先获取上传人的用户名,"operName",并作为一个参数,传入上传文件FileUploadUtils.upload方法中
         * 这样新建的线程不需要再使用SecurityUtils.getUsername();这个方法去获取上传人的用户名,可以直接用传入的参数"operName"
         *
         * CompletableFuture,
         */

        CompletableFuture<Void> uploadFuture = CompletableFuture.runAsync(() -> {
            try {
                
                Map map = FileUploadUtils.upload(filePath, Path, fileName, operName, file, myArray);
                String file_path = String.valueOf(map.get("file_path"));
//                http127.0.0.19090profile/exam/2023/12/成绩上传源文件@admin_20231220164926A001.xlsx
//                http://localhost:9090/profile/upload/exam/2023/12/成绩上传源文件@admin_20231219095943A001.xlsx
                file_path = protocol+"://"+clientIP +":"+ String.valueOf(port)+"/" + file_path;
                map.put("file_path",file_path);
                map.put("createby",operName);
                map.put("file_type","成绩上传");
                competitionFileInfoService.insertCompetitionFileInfo(map);
            } catch (Exception e) {
                // 处理异常情况
                e.printStackTrace();
                isExceptionOccurred.set(true);
            }
        });

        // 解析 Excel 文件并生成结果
        ExcelUtil<CompetitionExamImport> util = new ExcelUtil<CompetitionExamImport>(CompetitionExamImport.class);
        List<CompetitionExamImport> competitionExamImportList = util.importExcel(file.getInputStream());
        message[0] = competitionExamService.importExam(competitionExamImportList, updateSupport, operName);

        // 当上传操作完成时，返回结果
        return uploadFuture.thenApply(v -> {
            if (isExceptionOccurred.get()) {
                return error("解析Excel文件失败!请重试或联系管理员!");
            } else {
                return success(message[0]);
            }
        });
    }

















    @GetMapping("/importTemplate")
    public AjaxResult importTemplate()
    {
        ExcelUtil<CompetitionExam> util = new ExcelUtil<CompetitionExam>(CompetitionExam.class);
        return util.importTemplateExcel("用户数据");
    }


}
